using System;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using FluentSilverlight.Utility.Reflection;
using FluentSilverlight.ValueConverters;

namespace FluentSilverlight.Expressions.TextItems
{
    public class TextBoxExpression<TModel> : ControlExpression<TextBoxExpression<TModel>, TModel, TextBox>
        where TModel : class
    {
        private readonly Expression<Func<TModel, object>> textExpression;
        private Expression<Func<TModel, object>> readOnlyExpression;
        private Expression<Func<TModel, object>> interactableExpression;

        private readonly TModel model;
        private BindingMode bindingMode = BindingMode.TwoWay;
        private bool isReadOnly;
        private TextAlignment textAlignment = System.Windows.TextAlignment.Left;
        private int maxLength = 0;
        private string watermark;

        public TextBoxExpression(TModel model, Expression<Func<TModel, object>> expression)
        {
            this.model = model;
            textExpression = expression;
            Name(string.Format("{0}_{1}", ReflectionHelper.GetAccessor(expression).Name, Guid.NewGuid()));
        }

        public TextBoxExpression<TModel> MaxLength(int value)
        {
            maxLength = value;
            return thisInstance();
        }

        public TextBoxExpression<TModel> ReadOnly(Expression<Func<TModel, object>> expression)
        {
            readOnlyExpression = expression;
            return this;
        }

        public TextBoxExpression<TModel> Interactable(Expression<Func<TModel, object>> expression)
        {
            interactableExpression = expression;
            return this;
        }

        public TextBoxExpression<TModel> ReadOnly()
        {
            isReadOnly = true;
            return thisInstance();
        }

        public TextBoxExpression<TModel> Watermark(string value)
        {
            watermark = value;
            return thisInstance();
        }

        public BindModeExpression<TextBoxExpression<TModel>> BindMode
        {
            get { return new BindModeExpression<TextBoxExpression<TModel>>(this, b => bindingMode = b); }
        }

        public TextAlignmentExpression<TextBoxExpression<TModel>> TextAlignment
        {
            get { return new TextAlignmentExpression<TextBoxExpression<TModel>>(this, b => textAlignment = b); }
        }

        protected override TextBoxExpression<TModel> thisInstance()
        {
            return this;
        }

        protected override void BuildUp(TextBox element)
        {
            base.BuildUp(element);

            element.TextAlignment = textAlignment;
            element.MaxLength = maxLength;
            element.IsReadOnly = isReadOnly;

            if(watermark == null)
            {
                propertyBinder.SetBinding(textExpression, TextBox.TextProperty, bindingMode);
            }
            else
            {
                var watermarker = new Watermarker<TModel>(model, textExpression, element, watermark);
            }
            propertyBinder.SetBinding(readOnlyExpression, TextBox.IsReadOnlyProperty);
            propertyBinder.SetBindingWithConversion<BooleanToNotBooleanConverter>(interactableExpression, TextBox.IsReadOnlyProperty);
        }

        public static implicit operator TextBox(TextBoxExpression<TModel> expression)
        {
            var textBox = new TextBox();
            expression.BuildUp(textBox);
            return textBox;
        }
    }
}